package com.baizhi.dao;

import com.baizhi.entity.Book;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Repository
public class CustomerBookRepository implements CustomerBookReposity {
    @Autowired
    private ElasticsearchTemplate et;

    @Override
    public List<Book> selectByHighligter(String name, int pageNo, int limit) {
        //查询策略
        TermQueryBuilder builder = QueryBuilders.termQuery("name", name);
        //高亮
        HighlightBuilder.Field builder1 = new HighlightBuilder.Field("name");
        //准备查询条件。querySearch对象
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(builder)//封装查询条件
                .withHighlightFields(builder1)//高亮查询的条件
                .withPageable(PageRequest.of(pageNo-1, limit)) //page的0代表第一页
                .build();
        //这个方法可以查询数据，需要三个参数。1.查询的条件。2.查询的数据要封装到哪个类中。3.查询结果跟实体类的映射
        AggregatedPage<Book> books = et.queryForPage(searchQuery, Book.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                SearchHits hits = searchResponse.getHits();
                List<Book> bookList = new ArrayList<>();
                for (SearchHit hit : hits) {
                    Book book = new Book();
                    Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                    Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                    HighlightField hf = highlightFields.get("name");
                    if (hf != null) {
                        Text text = hf.getFragments()[0];
                        book.setName(text.toString());
                    } else {
                        book.setName((String) sourceAsMap.get("name"));
                    }
                    book.setId(Long.parseLong(hit.getId()));
                    book.setAuthor((String) sourceAsMap.get("author"));
                    bookList.add(book);
                }
                return new AggregatedPageImpl<T>((List<T>) bookList);
            }
        });
        return books.getContent();
    }

}
